package cn.edu.tju.elm.controller;

import cn.edu.tju.core.model.HttpResult;
import cn.edu.tju.core.model.ResultCodeEnum;
import cn.edu.tju.core.model.User;
import cn.edu.tju.core.security.service.UserService;
import cn.edu.tju.core.security.PermissionUtils;
import cn.edu.tju.elm.dto.AddressResponseDTO;
import cn.edu.tju.elm.mapper.AddressMapper;
import cn.edu.tju.elm.model.DeliveryAddress;
//import cn.edu.tju.elb.service.AddressService;
import cn.edu.tju.elm.service.AddressService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/api/addresses")
@Tag(name="管理地址", description = "对配送地址的增删改查")
public class AddressController {
//    @Autowired
//    private AddressService addressService;

    @Autowired
    private UserService userService;
    @Autowired
    private AddressService addressService;

    @Autowired
    private AddressMapper addressMapper;

    @Autowired
    private PermissionUtils permissionUtils;

    @PostMapping()
    @Operation(summary = "增加地址", description = "根据请求添加地址")
    public HttpResult<DeliveryAddress> addDeliveryAddress(@RequestBody DeliveryAddress deliveryAddress) {
        try {
            User user = userService.getUserWithAuthorities().get();
            LocalDateTime now = LocalDateTime.now();
            deliveryAddress.setCustomer(user);
            deliveryAddress.setCreator(user.getId());
            deliveryAddress.setCreateTime(now);
            deliveryAddress.setUpdater(user.getId());
            deliveryAddress.setUpdateTime(now);
            deliveryAddress.setDeleted(false);
            DeliveryAddress d = addressService.addAddress(deliveryAddress);
            return HttpResult.success(d);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "添加地址失败: " + e.getMessage());
        }
    }

    @GetMapping()
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessAddressData(#id)")
    @Operation(summary = "通过用户id查询地址", description = "通过用户id查找所有地址")
    public HttpResult<List<AddressResponseDTO>> getAllAddresses(@RequestParam("user") Long id) {
        try {
            List<DeliveryAddress> addresses = addressService.getAddressesByUserId(id);
            List<AddressResponseDTO> responseDTOs = addressMapper.addressesToResponseDTOs(addresses);
            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询地址失败: " + e.getMessage());
        }
    }

    @GetMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessAddressData(@addressService.getAddressById(#id).get().getCustomer().getId())")
    @Operation(summary = "通过地址id查询地址", description = "通过地址id查找的一条地址")
    public HttpResult<AddressResponseDTO> getAddressById(@PathVariable("id") Long id) {
        try {
            Optional<DeliveryAddress> address = addressService.getAddressById(id);
            if (address.isPresent()) {
                AddressResponseDTO responseDTO = addressMapper.addressToResponseDTO(address.get());
                return HttpResult.success(responseDTO);
            } else {
                return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "地址不存在");
            }
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询地址失败: " + e.getMessage());
        }
    }

    @GetMapping("/search")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessAddressData(#userId)")
    @Operation(summary = "根据地址内容搜索地址")
    public HttpResult<List<AddressResponseDTO>> searchAddressesByContent(@RequestParam String content, 
                                                                         @RequestParam("user") Long userId) {
        try {
            List<DeliveryAddress> addresses = addressService.getAddressesByContentContaining(content, userId);
            List<AddressResponseDTO> responseDTOs = addressMapper.addressesToResponseDTOs(addresses);
            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "搜索地址失败: " + e.getMessage());
        }
    }

    @GetMapping("/by-contact")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessAddressData(#userId)")
    @Operation(summary = "根据联系人姓名查询地址")
    public HttpResult<List<AddressResponseDTO>> getAddressesByContactName(@RequestParam String contactName, 
                                                                          @RequestParam("user") Long userId) {
        try {
            List<DeliveryAddress> addresses = addressService.getAddressesByContactNameContaining(contactName, userId);
            List<AddressResponseDTO> responseDTOs = addressMapper.addressesToResponseDTOs(addresses);
            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "根据联系人查询地址失败: " + e.getMessage());
        }
    }

    @GetMapping("/by-phone")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessAddressData(#userId)")
    @Operation(summary = "根据联系电话查询地址")
    public HttpResult<List<AddressResponseDTO>> getAddressesByPhone(@RequestParam String phone, 
                                                                    @RequestParam("user") Long userId) {
        try {
            List<DeliveryAddress> addresses = addressService.getAddressesByPhone(phone, userId);
            List<AddressResponseDTO> responseDTOs = addressMapper.addressesToResponseDTOs(addresses);
            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "根据电话查询地址失败: " + e.getMessage());
        }
    }

    @GetMapping("/current-user")
    @Operation(summary = "查询当前用户的所有地址")
    public HttpResult<List<AddressResponseDTO>> getCurrentUserAddresses() {
        try {
            User user = userService.getUserWithAuthorities().get();
            List<DeliveryAddress> addresses = addressService.getAddressesByUserId(user.getId());
            List<AddressResponseDTO> responseDTOs = addressMapper.addressesToResponseDTOs(addresses);
            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询当前用户地址失败: " + e.getMessage());
        }
    }

    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessAddressData(@addressService.getAddressById(#id).get().getCustomer().getId())")
    @Operation(summary = "删除地址")
    public HttpResult<String> deleteAddress(@PathVariable("id") Long id){
        try {
            addressService.deleteAddress(id);
            return HttpResult.success("删除成功");
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "删除地址失败: " + e.getMessage());
        }
    }

    @PutMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessAddressData(@addressService.getAddressById(#id).get().getCustomer().getId())")
    @Operation(summary = "修改地址")
    public HttpResult<AddressResponseDTO> updateAddress(@PathVariable("id") Long id, @RequestBody DeliveryAddress deliveryAddress) {
        try {
            User user = userService.getUserWithAuthorities().get();
            deliveryAddress.setId(id);
            deliveryAddress.setUpdater(user.getId());
            deliveryAddress.setUpdateTime(LocalDateTime.now());
            DeliveryAddress updatedAddress = addressService.updateAddress(deliveryAddress);
            AddressResponseDTO responseDTO = addressMapper.addressToResponseDTO(updatedAddress);
            return HttpResult.success(responseDTO);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "修改地址失败: " + e.getMessage());
        }
    }

    @PatchMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessAddressData(@addressService.getAddressById(#id).get().getCustomer().getId())")
    @Operation(summary = "部分修改地址")
    public HttpResult<AddressResponseDTO> partiallyUpdateAddress(@PathVariable("id") Long id, @RequestBody DeliveryAddress deliveryAddress) {
        try {
            User user = userService.getUserWithAuthorities().get();
            Optional<DeliveryAddress> existingAddress = addressService.getAddressById(id);
            if (existingAddress.isPresent()) {
                DeliveryAddress address = existingAddress.get();
                // 只更新非空字段
                if (deliveryAddress.getContactName() != null) {
                    address.setContactName(deliveryAddress.getContactName());
                }
                if (deliveryAddress.getContactSex() != null) {
                    address.setContactSex(deliveryAddress.getContactSex());
                }
                if (deliveryAddress.getContactTel() != null) {
                    address.setContactTel(deliveryAddress.getContactTel());
                }
                if (deliveryAddress.getAddress() != null) {
                    address.setAddress(deliveryAddress.getAddress());
                }
                if (deliveryAddress.getCustomer() != null) {
                    address.setCustomer(deliveryAddress.getCustomer());
                }
                if (deliveryAddress.getDeleted() != null) {
                    address.setDeleted(deliveryAddress.getDeleted());
                }
                address.setUpdater(user.getId());
                address.setUpdateTime(LocalDateTime.now());
                DeliveryAddress updatedAddress = addressService.updateAddress(address);
                AddressResponseDTO responseDTO = addressMapper.addressToResponseDTO(updatedAddress);
                return HttpResult.success(responseDTO);
            } else {
                return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "地址不存在");
            }
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "部分修改地址失败: " + e.getMessage());
        }
    }
}
